/*
 * NISTMessenger.java
 *
 * Created on January 27, 2004, 6:53 PM
 */

package gov.nist.applet.phone.ua.gui;

import gov.nist.applet.phone.media.messaging.VoiceRecorder;
import gov.nist.applet.phone.ua.ChatSessionManager;
import gov.nist.applet.phone.ua.Configuration;
import gov.nist.applet.phone.ua.MessengerController;
import gov.nist.applet.phone.ua.MessengerManager;
import gov.nist.applet.phone.ua.RegisterStatus;
import gov.nist.applet.phone.ua.StopMessenger;
import gov.nist.applet.phone.ua.gui.SysConfigFrame.MyCellRender;
import gov.nist.applet.phone.ua.presence.Subscriber;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import com.dtec.common.util.SettingUtil;
import com.dtec.resource.settingInfo.Account;
import com.dtec.resource.settingInfo.Contact;
import com.dtec.resource.settingInfo.History;
import com.dtec.swing.RoundButton;
import com.sun.xml.internal.ws.util.StringUtils;

/**
 * This application has been designed in following the MVC design pattern Thus,
 * this class is part of the View.
 * 
 * @author Jean Deruelle
 * 
 *         <a href="{@docRoot} /uncopyright.html">This code is in the public
 *         domain.</a>
 */
public class NISTMessenger extends javax.swing.JFrame implements
		java.util.Observer, NISTMessengerGUI {
	Configuration configuration;
	/* MVC attributes */
	private MessengerManager sipMeetingManager;
	private MessengerController controllerMeeting;
	private ChatSessionManager chatSessionManager;

	public ChatSessionManager getChatSessionManager() {
		return chatSessionManager;
	}

	private String path = "xmlSource/ServerInfo.xml";
	private Account defaultAccount = null;

	/** Creates new form NISTMessenger */
	public NISTMessenger() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			SwingUtilities.updateComponentTreeUI(this);
		} catch (Exception exe) {
			exe.printStackTrace();
		}
		defaultAccount = SettingUtil
				.getDefaultAccount("xmlSource/ServerInfo.xml");
		configuration = new Configuration(defaultAccount);
		chatSessionManager = new ChatSessionManager();
		sipMeetingManager = new MessengerManager(configuration, this);
		sipMeetingManager.addObserver(this);
		controllerMeeting = new MessengerController(sipMeetingManager,
				chatSessionManager, this);
		initComponents();
		listModel = new DefaultListModel();

		// Create the list and put it in a scroll pane.
		jList1 = new JList(listModel);
		/*
		 * jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		 * jList1.addMouseListener(new MouseAdapter() { public void
		 * mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { String
		 * contactAddress = (String) listModel.elementAt(jList1
		 * .getSelectedIndex()); if (contactAddress.trim().indexOf('(') != -1)
		 * contactAddress = contactAddress.substring(0,
		 * contactAddress.trim().indexOf("(")); // check if a chat frame has
		 * already been opened ChatFrame chatFrame = (ChatFrame)
		 * chatSessionManager .getChatFrame(contactAddress); if (chatFrame ==
		 * null) { // emulate button click chatFrame = new ChatFrame(this,
		 * contactAddress, sipMeetingManager, chatSessionManager);
		 * chatSessionManager.addChatSession(contactAddress, chatFrame);
		 * chatFrame.show(); } else { chatFrame.show(); } } } });
		 */

		JScrollPane listScrollPane = new JScrollPane(jList1);
		/*
		 * listScrollPane.setBounds(30, 100, 250, 150);
		 * mainPanel.add(listScrollPane); getContentPane().add(mainPanel); //
		 * Get current classloader ClassLoader cl =
		 * this.getClass().getClassLoader(); URL url =
		 * cl.getResource("images/short_nisthome_banner.jpg"); if (url != null)
		 * imageLabel.setIcon(new ImageIcon(url)); this.pack();
		 * this.setTitle("SIP Phone"); this.setSize(320, 520);
		 */
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {// GEN-BEGIN:initComponents

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			SwingUtilities.updateComponentTreeUI(this);
		} catch (Exception exe) {
			exe.printStackTrace();
		}

		this.setSize(302, 650);

		Toolkit kit = Toolkit.getDefaultToolkit();
		Dimension screenSize = kit.getScreenSize();
		int screenHeight = screenSize.height;
		int screenWidth = screenSize.width;
		int frameH = this.getHeight();
		int frameW = this.getWidth();
		this.setLocation((screenWidth - frameW) / 2,
				(screenHeight - frameH) / 2);

		this.setJMenuBar(getMainMenuBar());

		this.setLayout(null);

		this.add(getUserStatus());

		this.add(getDial());

		this.add(getContact());

		this.add(getDialPanel());

		this.setTitle("Sip Phone");
		this.setResizable(false);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent evt) {
				exitForm(evt);
			}
		});

		if (defaultAccount != null) {
			sipMeetingManager.register();
		}
		mainPanel = new javax.swing.JPanel();
		imageLabel = new javax.swing.JLabel();
		addContactButton = new javax.swing.JButton();
		removeContactButton = new javax.swing.JButton();
		jLabel1 = new javax.swing.JLabel();
		fileMenuBar1 = new javax.swing.JMenuBar();
		jMenu5 = new javax.swing.JMenu();
		jMenuItemConfiguration = new javax.swing.JMenuItem();
		jMenuItemRegister = new javax.swing.JMenuItem();
		jMenuItemUnregister = new javax.swing.JMenuItem();
		jMenuItemExit = new javax.swing.JMenuItem();
		jMenuStatus = new javax.swing.JMenu();
		showConnectionButton = new javax.swing.JButton(new ImageIcon(
				"images/left.jpg"));
		connectionFrame = null;
		onlineJRadioButtonMenuItem = new JRadioButtonMenuItem("Online");
		awayJRadioButtonMenuItem = new JRadioButtonMenuItem("Away");
		offlineJRadioButtonMenuItem = new JRadioButtonMenuItem("Be Right Back");
		busyJRadioButtonMenuItem = new JRadioButtonMenuItem("Busy");

		/*
		 * getContentPane().setLayout(null);
		 * 
		 * addWindowListener(new java.awt.event.WindowAdapter() { public void
		 * windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } });
		 * 
		 * mainPanel.setLayout(null);
		 * 
		 * mainPanel.setMinimumSize(new java.awt.Dimension(310, 500));
		 * mainPanel.setPreferredSize(new java.awt.Dimension(310, 500));
		 * imageLabel.setMaximumSize(new java.awt.Dimension(400, 50));
		 * imageLabel.setMinimumSize(new java.awt.Dimension(300, 50));
		 * imageLabel.setPreferredSize(new java.awt.Dimension(400, 50));
		 * mainPanel.add(imageLabel); imageLabel.setBounds(30, 0, 250, 50);
		 * 
		 * showConnectionButton.setOpaque(false); showConnectionButton
		 * .addActionListener(new java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * showConnectionButtonActionPerformed(evt); } });
		 * showConnectionButton.setBounds(280, 0, 30, 50);
		 * mainPanel.add(showConnectionButton);
		 * 
		 * addContactButton.setText("Add Contact");
		 * addContactButton.setOpaque(false);
		 * addContactButton.addActionListener(new
		 * java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * addContactButtonActionPerformed(evt); } });
		 * 
		 * mainPanel.add(addContactButton); addContactButton.setBounds(10, 400,
		 * 120, 40);
		 * 
		 * removeContactButton.setText("Remove Contact");
		 * removeContactButton.setEnabled(false); removeContactButton
		 * .addActionListener(new java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * removeContactButtonActionPerformed(evt); } });
		 * 
		 * mainPanel.add(removeContactButton);
		 * removeContactButton.setBounds(160, 400, 130, 40);
		 * 
		 * jLabel1.setText("Not Logged"); mainPanel.add(jLabel1);
		 * jLabel1.setOpaque(true); jLabel1.setBackground(new Color(204, 255,
		 * 204)); jLabel1.setBounds(30, 50, 250, 50);
		 * 
		 * getContentPane().add(mainPanel); mainPanel.setBounds(0, 0, 310, 500);
		 * 
		 * jMenu5.setText("Menu");
		 * jMenuItemConfiguration.setText("Configuration");
		 * jMenuItemConfiguration .addActionListener(new
		 * java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * jMenuItemConfigurationActionPerformed(evt); } });
		 * 
		 * jMenu5.add(jMenuItemConfiguration);
		 * 
		 * jMenuItemRegister.setText("Register");
		 * jMenuItemRegister.addActionListener(new
		 * java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * jMenuItemRegisterActionPerformed(evt); } });
		 * 
		 * jMenu5.add(jMenuItemRegister);
		 * 
		 * jMenuItemUnregister.setText("Unregister"); jMenuItemUnregister
		 * .addActionListener(new java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * jMenuItemUnregisterActionPerformed(evt); } });
		 * 
		 * jMenu5.add(jMenuItemUnregister);
		 * 
		 * jMenuStatus.setText("Status");
		 * onlineJRadioButtonMenuItem.addActionListener(new ActionListener() {
		 * public void actionPerformed(ActionEvent evt) {
		 * onlineActionPerformed(evt); } });
		 * 
		 * awayJRadioButtonMenuItem.addActionListener(new ActionListener() {
		 * public void actionPerformed(ActionEvent evt) {
		 * awayActionPerformed(evt); } });
		 * 
		 * offlineJRadioButtonMenuItem.addActionListener(new ActionListener() {
		 * public void actionPerformed(ActionEvent evt) {
		 * beRightBackActionPerformed(evt); } });
		 * 
		 * busyJRadioButtonMenuItem.addActionListener(new ActionListener() {
		 * public void actionPerformed(ActionEvent evt) {
		 * busyActionPerformed(evt); } }); statusGroup = new ButtonGroup();
		 * onlineJRadioButtonMenuItem.setSelected(true);
		 * statusGroup.add(onlineJRadioButtonMenuItem);
		 * statusGroup.add(offlineJRadioButtonMenuItem);
		 * statusGroup.add(busyJRadioButtonMenuItem);
		 * statusGroup.add(awayJRadioButtonMenuItem);
		 * 
		 * jMenuStatus.add(awayJRadioButtonMenuItem);
		 * jMenuStatus.add(onlineJRadioButtonMenuItem);
		 * jMenuStatus.add(offlineJRadioButtonMenuItem);
		 * jMenuStatus.add(busyJRadioButtonMenuItem);
		 * 
		 * jMenu5.add(jMenuStatus);
		 * 
		 * jMenuItemExit.setText("Exit"); jMenuItemExit.addActionListener(new
		 * java.awt.event.ActionListener() { public void
		 * actionPerformed(java.awt.event.ActionEvent evt) {
		 * jMenuItemExitActionPerformed(evt); } });
		 * 
		 * jMenu5.add(jMenuItemExit);
		 * 
		 * fileMenuBar1.add(jMenu5);
		 * 
		 * setJMenuBar(fileMenuBar1);
		 * 
		 * this.setBounds(300, 200, 320, 520);
		 * 
		 * pack();
		 */
	}// GEN-END:initComponents

	/*---------------Menu Setting--------------*/

	private JMenuBar getMainMenuBar() {
		MainMenuBar = new JMenuBar();

		// 基本菜单
		jmBasic = new JMenu("基本");
		jmiNewAccount = new JMenuItem("新建账户");
		jmiNewAccount.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/menu/addAccountMenu.png")));
		jmiAccountManage = new JMenuItem("管理账户");
		jmiAccountManage.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/menu/accountManage.png")));
		jmiAddContact = new JMenuItem("添加联系人");
		jmiAddContact.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/menu/addContact.png")));
		jmiExit = new JMenuItem("退出");
		jmiExit.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/menu/quit.png")));
		jmBasic.add(jmiNewAccount);
		jmBasic.add(jmiAccountManage);
		jmBasic.addSeparator();
		jmBasic.add(jmiAddContact);
		jmBasic.addSeparator();
		jmBasic.add(jmiExit);

		// 工具菜单
		jmTools = new JMenu("工具");
		jmiSettings = new JMenuItem("设置");
		jmiSettings.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/menu/configureIcon.png")));
		jmTools.add(jmiSettings);
		MainMenuBar.add(jmBasic);
		MainMenuBar.add(jmTools);

		// 帮助
		jmHelp = new JMenu("帮助");
		MainMenuBar.add(jmHelp);

		// 关于
		jmAbout = new JMenu("关于");
		MainMenuBar.add(jmAbout);

		// MenuItem事件注册

		jmiNewAccount.addActionListener(menuItemListener);
		jmiExit.addActionListener(menuItemListener);
		jmiAccountManage.addActionListener(menuItemListener);
		jmiAddContact.addActionListener(menuItemListener);
		jmiSettings.addActionListener(menuItemListener);

		return MainMenuBar;
	}

	/*---------------Panel Setting--------------*/

	private JPanel getUserStatus() {
		jpUserStatus = new JPanel();
		jpUserStatus.setSize(294, 60);
		jpUserStatus.setLocation(0, locationY);
		jpUserStatus.setBackground(Color.WHITE);
		locationY += jpUserStatus.getHeight();
		jpUserStatus.setLayout(null);
		// Core Design
		// Left
		jbPersonPhoto = new JButton();
		jbPersonPhoto.setSize(50, 50);
		jbPersonPhoto.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/userstatus/account.png")));
		jbPersonPhoto.setLocation(5, 5);
		jbPersonPhoto.setCursor(new Cursor(Cursor.HAND_CURSOR));
		jpUserStatus.add(jbPersonPhoto);
		// Center
		jlAccountInfo = new JLabel("No Account"/*
												 * , new ImageIcon(
												 * "images/userstatus/account.png"
												 * ), JLabel.LEFT
												 */);
		jlAccountInfo.setSize(130, 50);
		jlAccountInfo.setLocation(70, 5);
		jpUserStatus.add(jlAccountInfo);
		// Right
		jlStatusTitle = new JLabel("当前状态", new ImageIcon(
				"images/menu/configureIcon.png"), JLabel.LEFT);
		jpmStatus = new JPopupMenu("------");
		jmiFree = new JMenuItem("在线");
		jmiOffLine = new JMenuItem("离线");

		jmiFree.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/userstatus/online.png")));
		jmiOffLine.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/userstatus/offline.png")));
		jmiFree.addActionListener(userStatusListener);
		jmiOffLine.addActionListener(userStatusListener);
		jpmStatus.add(jmiFree);
		jpmStatus.add(jmiOffLine);
		jlStatusTitle.setComponentPopupMenu(jpmStatus);
		jlStatusTitle.setSize(90, 20);
		jlStatusTitle.setLocation(210, 19);
		jlStatusTitle.setCursor(new Cursor(Cursor.HAND_CURSOR));
		jlStatusTitle.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent event) {
				if (event.getModifiers() == InputEvent.BUTTON1_MASK) {
					jpmStatus.show(event.getComponent(), 2, 19);
				}
			}

			public void mouseEntered(MouseEvent event) {
				jlStatusTitle.setForeground(Color.BLUE);
			}

			public void mouseExited(MouseEvent event) {
				jlStatusTitle.setForeground(null);
			}
		});

		jpUserStatus.add(jlStatusTitle);
		return jpUserStatus;
	}

	private JPanel getDial() {
		jpDial = new JPanel() {
			private static final long serialVersionUID = 1L;

			protected void paintComponent(Graphics g) {
				super.paintComponent(g);
				ImageIcon img = new ImageIcon(
						NISTMessenger.class
								.getResource("/images/dial/input1.png"));
				g.drawImage(img.getImage(), 0, 0, null);
			};
		};
		jpDial.setLayout(null);
		jpDial.setSize(295, 52);
		jpDial.setLocation(0, locationY);
		jpDial.setBackground(Color.WHITE);
		locationY += jpDial.getHeight();

		// Core Design
		// Left
		jtfContactAddr = new JTextField(20);
		jtfContactAddr.setSize(130, 25);
		jtfContactAddr.setLocation(50, 13);
		jtfContactAddr.addKeyListener(new KeyAdapter() {
			public void keyTyped(KeyEvent e) {
				String query = jtfContactAddr.getText();
				contacts = SettingUtil.getContacts(query,
						SettingUtil.ContactPath);
				histories = SettingUtil.getHistory(query,
						SettingUtil.HistoryPath);
				// updateQueryInfo();
			}
		});

		jbDelete = new RoundButton("", 155, 180, 200);
		jbDelete.setIcon(new ImageIcon(NISTMessenger.class
				.getResource("/images/dial/delete.png")));
		jbDelete.setSize(16, 16);
		jbDelete.setLocation(188, 17);
		jbDelete.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent event) {
				String ca = jtfContactAddr.getText();
				if (ca.length() > 0) {
					jtfContactAddr.setText(ca.substring(0, ca.length() - 1));
				}
			}
		});

		jpDial.add(jbDelete);

		// Right
		jbAudioCall = new JButton(new ImageIcon(
				NISTMessenger.class.getResource("/images/dial/audio.png")));
		// jbAudioCall=new RoundButton("",155,180,200);
		// jbAudioCall.setIcon(new
		// ImageIcon(NISTMessenger.class.getResource("/images/dial/audio.png")));
		jbAudioCall.setSize(32, 32);
		jbAudioCall.setLocation(225, 9);
		jbAudioCall.addMouseListener(new CallButtonMouseClickAdapter());
		jpDial.add(jtfContactAddr);

		jbVideoCall = new JButton(new ImageIcon(
				NISTMessenger.class.getResource("/images/dial/video.png")));
		jbVideoCall.setSize(32, 32);
		jbVideoCall.addMouseListener(new CallButtonMouseClickAdapter());
		jbVideoCall.setLocation(259, 9);

		jpDial.add(jbAudioCall);
		jpDial.add(jbVideoCall);

		return jpDial;
	}

	private JTree getQueryTree() {
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("queryList");
		model = new DefaultTreeModel(root);
		contacts = SettingUtil.getContacts(null, SettingUtil.ContactPath);
		contact = new DefaultMutableTreeNode("联系人(" + contacts.size() + ")");
		contact.setAllowsChildren(true);
		cnodes = new ArrayList<DefaultMutableTreeNode>();
		for (Contact c : contacts) {
			String t = c.getName() + "-" + c.getContactAddress();
			DefaultMutableTreeNode cn = new DefaultMutableTreeNode(t);
			cnodes.add(cn);
			cn.setAllowsChildren(false);
			contact.add(cn);
		}
		root.add(contact);
		histories = SettingUtil.getHistory(null, SettingUtil.HistoryPath);
		history = new DefaultMutableTreeNode("历史记录(" + histories.size() + ")");
		history.setAllowsChildren(true);
		hnodes = new ArrayList<DefaultMutableTreeNode>();
		for (History h : histories) {
			String t = h.getContactAddress() + "(" + h.getDialDate() + ")"
					+ h.getDialType();
			DefaultMutableTreeNode hn = new DefaultMutableTreeNode(t);
			hnodes.add(hn);
			hn.setAllowsChildren(false);
			history.add(hn);
		}
		root.add(history);
		tree = new JTree(root, true);
		tree.expandRow(0);
		tree.expandRow(1);
		DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
		renderer.setLeafIcon(new ImageIcon(SysConfigFrame.class
				.getResource("/images/queryinfo/guest.png")));
		renderer.setClosedIcon(new ImageIcon(SysConfigFrame.class
				.getResource("/images/queryinfo/rightArrow.png")));
		renderer.setOpenIcon(new ImageIcon(SysConfigFrame.class
				.getResource("/images/queryinfo/downArrow.png")));
		tree.setCellRenderer(renderer);
		tree.setRootVisible(false);
		tree.addTreeSelectionListener(new TreeSelectionListener() {

			@Override
			public void valueChanged(TreeSelectionEvent arg0) {
				TreePath path = tree.getSelectionPath();
				if (path == null)
					return;
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) path
						.getLastPathComponent();
				String c = (String) selectedNode.getUserObject();
				if (selectedNode.isLeaf()) {
					DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode
							.getParent();
					System.out.println(parent.getUserObject());
					if (((String) parent.getUserObject()).contains("联系人")) {
						jtfContactAddr
								.setText(org.apache.commons.lang.StringUtils
										.split(c, "-")[1]);
					} else if (((String) parent.getUserObject())
							.contains("历史记录")) {
						jtfContactAddr
								.setText(org.apache.commons.lang.StringUtils
										.split(c, "(")[0]);
					}
				}
			}
		});
		return tree;
	}

	private JScrollPane getContact() {
		jspContact = new JScrollPane(getQueryTree());
		jspContact.setSize(295, 280);
		jspContact.setLocation(0, locationY);
		jspContact.setBackground(Color.WHITE);
		jspContact.setOpaque(false);
		locationY += jspContact.getHeight();
		return jspContact;
	}

	private JPanel getDialPanel() {
		jpDialPanel = new JPanel();
		jpDialPanel.setSize(220, 170);
		jpDialPanel.setLocation(42, locationY + 10);

		// Core Design
		jpDialPanel.setLayout(new GridLayout(4, 3, 10, 10));
		dialBtns = new JButton[12];
		int width = jpDialPanel.getWidth();
		int height = jpDialPanel.getHeight();
		for (int i = 0; i < 12; i++) {
			dialBtns[i] = new JButton();
			dialBtns[i].setSize(80, 60);
			dialBtns[i].setName("db" + i);
			dialBtns[i].addMouseListener(new DialButtonMouseClickAdapter());
		}
		try {
			dialBtns[0].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/zero.png")));
			dialBtns[1].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/one.png")));
			dialBtns[2].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/two.png")));
			dialBtns[3].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/three.png")));
			dialBtns[4].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/four.png")));
			dialBtns[5].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/five.png")));
			dialBtns[6].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/six.png")));
			dialBtns[7].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/seven.png")));
			dialBtns[8].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/eight.png")));
			dialBtns[9].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/nine.png")));
			dialBtns[10].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/star.png")));
			dialBtns[11].setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/dialPanel/diez.png")));
		} catch (Exception e) {
			e.printStackTrace();
		}
		for (int i = 1; i <= 9; i++) {
			jpDialPanel.add(dialBtns[i]);
		}
		jpDialPanel.add(dialBtns[10]);
		jpDialPanel.add(dialBtns[0]);
		jpDialPanel.add(dialBtns[11]);

		// jpDialPanel.setBackground(Color.magenta);
		return jpDialPanel;
	}

	// Event Listener/Adapter

	class DialButtonMouseClickAdapter extends MouseAdapter {
		public void mouseClicked(MouseEvent event) {
			JButton jbt = (JButton) event.getSource();
			int index = Integer.parseInt(jbt.getName().substring(2,
					jbt.getName().length()));
			String contactAddr = jtfContactAddr.getText();
			if (index >= 0 && index <= 9) {
				jtfContactAddr.setText(contactAddr + index);
			} else if (index == 10) {
				jtfContactAddr.setText(contactAddr + "*");
			} else if (index == 11) {
				jtfContactAddr.setText(contactAddr + "#");
			}
		}
	}

	class CallButtonMouseClickAdapter extends MouseAdapter {
		public void mouseClicked(MouseEvent event) {
			JButton jbt = (JButton) event.getSource();
			if (configuration == null) {
				configuration = sipMeetingManager.getMessageListener()
						.getConfiguration();
			}
			if (jtfContactAddr.getText().equals("")) {
				JOptionPane.showConfirmDialog(null, "请输入通信地址", "Warning",
						JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
				return;
			}
			if (!((jbt.equals(jbAudioCall) || jbt.equals(jbVideoCall)) && sipMeetingManager
					.getRegisterStatus().equalsIgnoreCase(
							RegisterStatus.REGISTERED))) {
				JOptionPane.showConfirmDialog(null, "当前账户处于离线状态，不能进行通话！",
						"Warning", JOptionPane.CLOSED_OPTION,
						JOptionPane.WARNING_MESSAGE);
				return;
			}
			if (jbt.equals(jbAudioCall)) {
				String contactAddress = (String) jtfContactAddr.getText();
				if (!"".equals(contactAddress)) {
					if (contactAddress.trim().matches("\\d+")) {
						contactAddress += "@" + configuration.outboundProxy;
						Subscriber subscriber = new Subscriber(contactAddress);
						sipMeetingManager.getPresentityManager().addSubscriber(
								subscriber);
						sipMeetingManager.sendSubscribe(contactAddress);
						// controllerMeeting.addContact(contactAddress);
					} else if (org.apache.commons.lang.StringUtils.split(
							contactAddress, "@").length == 2) {
						Subscriber subscriber = new Subscriber(contactAddress);
						sipMeetingManager.getPresentityManager().addSubscriber(
								subscriber);
						sipMeetingManager.sendSubscribe(contactAddress);
					} else {
						JOptionPane.showMessageDialog(main,
								"The contact must be of the form user@domain"
										+ ", the contact has not been added",
								"Contact Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					// 记录拨打历史记录
					History h = new History();
					h.setContactAddress(contactAddress);
					h.setDialDate(null);
					h.setDialType("out");
					SettingUtil.addHistory(h, SettingUtil.HistoryPath);
				}

				// if (contactAddress.trim().indexOf('(') != -1)
				// contactAddress = contactAddress.substring(0,
				// contactAddress.trim().indexOf("("));
				// check if a chat frame has already been opened
				ChatFrame chatFrame = (ChatFrame) chatSessionManager
						.getChatFrame(contactAddress);
				if (chatFrame == null) {
					// emulate button click
					chatFrame = new ChatFrame(this, contactAddress,
							sipMeetingManager, chatSessionManager);
					chatSessionManager
							.addChatSession(contactAddress, chatFrame);
					chatFrame.setVisible(true);
				} else {
					chatFrame.setVisible(true);
				}
				chatFrame.dial("audio");
			} else if (jbt.equals(jbVideoCall)) {
				String contactAddress = (String) jtfContactAddr.getText();

				if (!"".equals(contactAddress)) {
					if (contactAddress.trim().matches("\\d+")) {
						contactAddress += "@" + configuration.outboundProxy;
						Subscriber subscriber = new Subscriber(contactAddress);
						sipMeetingManager.getPresentityManager().addSubscriber(
								subscriber);
						sipMeetingManager.sendSubscribe(contactAddress);
						// controllerMeeting.addContact(contactAddress);
					} else if (org.apache.commons.lang.StringUtils.split(
							contactAddress, "@").length == 2) {
						Subscriber subscriber = new Subscriber(contactAddress);
						sipMeetingManager.getPresentityManager().addSubscriber(
								subscriber);
						sipMeetingManager.sendSubscribe(contactAddress);
					} else {
						JOptionPane.showMessageDialog(main,
								"The contact must be of the form user@domain"
										+ ", the contact has not been added",
								"Contact Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					// 记录拨打历史记录
					History h = new History();
					h.setContactAddress(contactAddress);
					h.setDialDate(null);
					h.setDialType("out");
					SettingUtil.addHistory(h, SettingUtil.HistoryPath);
				}

				// if (contactAddress.trim().indexOf('(') != -1)
				// contactAddress = contactAddress.substring(0,
				// contactAddress.trim().indexOf("("));
				// check if a chat frame has already been opened
				ChatFrame chatFrame = (ChatFrame) chatSessionManager
						.getChatFrame(contactAddress);
				if (chatFrame == null) {
					// emulate button click
					chatFrame = new ChatFrame(this, contactAddress,
							sipMeetingManager, chatSessionManager);
					chatSessionManager
							.addChatSession(contactAddress, chatFrame);
					chatFrame.show();
				} else {
					chatFrame.show();
				}
				chatFrame.dial("video");
			}
		}
	}

	ActionListener menuItemListener = new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource().equals(jmiNewAccount)) {
				new ConfigurationFrame(sipMeetingManager).setVisible(true);
			} else if (e.getSource().equals(jmiExit)) {
				close();
			} else if (e.getSource().equals(jmiAccountManage)) {
				new SysConfigFrame(sipMeetingManager, chatSessionManager,
						SysConfigFrame.CONFIGURE_ACCOUNT).setVisible(true);
			} else if (e.getSource().equals(jmiSettings)) {
				new SysConfigFrame(sipMeetingManager, chatSessionManager,
						SysConfigFrame.CONFIGURE_ADVANCE).setVisible(true);
			} else if (e.getSource().equals(jmiAddContact)) {

			}
		}
	};

	ActionListener userStatusListener = new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource().equals(jmiOffLine)
					&& sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
							RegisterStatus.REGISTERED)) {
				sipMeetingManager.unRegister();
				jlStatusTitle.setText("离线");

			} else if (e.getSource().equals(jmiFree)
					&& sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
							RegisterStatus.NOT_REGISTERED)) {
				sipMeetingManager.register();
				jlStatusTitle.setText("在线");
			}
		}
	};

	private void showConnectionButtonActionPerformed(ActionEvent evt) {
		if (connectionFrame == null) {
			int x = this.getX() + this.getWidth();
			int y = this.getY();
			connectionFrame = new ConnectionFrame(x, y, this.getWidth(),
					this.getHeight(), this);
		}
		if (connectionFrame.isVisible()) {
			showConnectionButton.setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/left.jpg")));
			connectionFrame.setVisible(false);
		} else {
			showConnectionButton.setIcon(new ImageIcon(NISTMessenger.class
					.getResource("/images/right.jpg")));
			connectionFrame.setVisible(true);
		}
	}

	private void jMenuItemExitActionPerformed(java.awt.event.ActionEvent evt) {
		close();
	}

	private void jMenuItemUnregisterActionPerformed(
			java.awt.event.ActionEvent evt) {
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.NOT_REGISTERED)) {
			JOptionPane
					.showMessageDialog(
							this,
							"You are currently not registered, please register to un-register",
							"Already un-registered", JOptionPane.ERROR_MESSAGE);
			return;
		}
		unRegister();
		controllerMeeting.undisplayAllContact();
		removeContactButton.setEnabled(false);
	}

	private void jMenuItemRegisterActionPerformed(java.awt.event.ActionEvent evt) {
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			JOptionPane.showMessageDialog(this,
					"You are already registered, please un-register before",
					"Already registered", JOptionPane.ERROR_MESSAGE);
			return;
		}
		sipMeetingManager.register();
		controllerMeeting.displayAllContact();
		removeContactButton.setEnabled(true);
	}

	private void jMenuItemConfigurationActionPerformed(
			java.awt.event.ActionEvent evt) {
		new ConfigurationFrame(sipMeetingManager).setVisible(true);
	}

	private void onlineActionPerformed(java.awt.event.ActionEvent evt) {
		jLabel1.setText("Logged as : " + configuration.userURI + " - Online");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"open", "online");
	}

	private void busyActionPerformed(java.awt.event.ActionEvent evt) {
		jLabel1.setText("Logged as : " + configuration.userURI + " - Busy");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inuse", "busy");
	}

	private void awayActionPerformed(java.awt.event.ActionEvent evt) {
		jLabel1.setText("Logged as : " + configuration.userURI + " - Away");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inactive", "away");
	}

	private void beRightBackActionPerformed(java.awt.event.ActionEvent evt) {
		jLabel1.setText("Logged as : " + configuration.userURI
				+ " - Be Right Back");
		sipMeetingManager.getPresentityManager().sendNotifyToAllSubscribers(
				"inactive", "berightback");
	}

	private void removeContactButtonActionPerformed(
			java.awt.event.ActionEvent evt) {
		controllerMeeting.removeContact();
	}

	private void addContactButtonActionPerformed(java.awt.event.ActionEvent evt) {
		if (!sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			JOptionPane.showMessageDialog(this,
					"You must be registered to add a new contact",
					"Contact Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		String contactAddress = (String) JOptionPane.showInputDialog(this,
				"Enter the contact address to add:\n", "Add Contact",
				JOptionPane.PLAIN_MESSAGE, null, null, null);
		System.out.println(contactAddress);
		if (contactAddress != null) {
			if (contactAddress.trim().matches("\\d+")) {
				contactAddress += "@" + defaultAccount.getProxyaddress();
				Subscriber subscriber = new Subscriber(contactAddress);
				sipMeetingManager.getPresentityManager().addSubscriber(
						subscriber);
				sipMeetingManager.sendSubscribe(contactAddress);
				controllerMeeting.addContact(contactAddress);
			} else {
				JOptionPane.showMessageDialog(this,
						"The contact must be of the form user@domain"
								+ ", the contact has not been added",
						"Contact Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}// GEN-LAST:event_addContactButtonActionPerformed

	/**
	 * Get the view component representing the logged status label
	 * 
	 * @return the logged status label
	 */
	public JLabel getLoggedStatusLabel() {
		return jlStatusTitle;
	}

	public JLabel getAccountLabel() {
		return jlAccountInfo;
	}

	/**
	 * Get the contact list from this frame
	 * 
	 * @return the contact list from this frame
	 */
	public JList getContactList() {
		return jList1;
	}

	/**
	 * Get the contact list from this frame
	 * 
	 * @return the contact list from this frame
	 */
	public JButton getRemoveContactButton() {
		return removeContactButton;
	}

	/**
     * 
     */
	public void update(java.util.Observable o, Object arg) {

	}

	/**
	 * Exit the Application
	 */
	private void exitForm(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_exitForm
		close();
	}// GEN-LAST:event_exitForm

	/**
     * 
     *
     */
	private void close() {
		unRegister();
		if (!VoiceRecorder.isClosed())
			VoiceRecorder.getInstance().close();
		new StopMessenger(sipMeetingManager.getMessageListener());
		System.exit(0);
	}

	/**
     * 
     *
     */
	protected void unRegister() {
		if (sipMeetingManager.getRegisterStatus().equalsIgnoreCase(
				RegisterStatus.REGISTERED)) {
			if (chatSessionManager.hasActiveSessions()) {
				int response = javax.swing.JOptionPane
						.showConfirmDialog(
								null,
								" All current sessions will be closed,\n"
										+ " do you still want to close the application ?",
								"Close the Application",
								javax.swing.JOptionPane.YES_NO_OPTION,
								javax.swing.JOptionPane.QUESTION_MESSAGE);
				if (response == javax.swing.JOptionPane.NO_OPTION)
					return;
				else if (response == javax.swing.JOptionPane.YES_OPTION) {
					chatSessionManager.closeAllSessions();
				}
			}
			sipMeetingManager.unRegister();
		}
	}

	/**
	 * Fatal error.
	 */
	public void fatalError(String errorText) {
		JOptionPane.showMessageDialog(this, errorText, "Fatal Error",
				JOptionPane.ERROR_MESSAGE);
		close();
	}

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		new NISTMessenger().setVisible(true);
	}

	private static final long serialVersionUID = 1L;

	private int locationY = 0;

	NISTMessenger main = null;

	/*---------------Menu----------------*/
	private JMenuBar MainMenuBar = null;

	/*-------------Basic Menu--------------*/
	private JMenu jmBasic = null;
	private JMenuItem jmiNewAccount = null;
	private JMenuItem jmiAccountManage = null;
	private JMenuItem jmiAddContact = null;
	private JMenuItem jmiExit = null;

	/*-------------Tools Menu--------------*/
	private JMenu jmTools = null;
	private JMenuItem jmiSettings = null;

	/*-------------Help Menu--------------*/
	private JMenu jmHelp = null;

	/*-------------About Menu--------------*/
	private JMenu jmAbout = null;

	/*-------------Panel--------------*/
	private JPanel jpUserStatus = null;
	private JButton jbPersonPhoto = null;
	private JLabel jlAccountInfo = null;
	private JLabel jlStatusTitle = null;
	private JPopupMenu jpmStatus = null;
	private JMenuItem jmiFree = null;
	private JMenuItem jmiOffLine = null;

	private JPanel jpDial = null;
	private JTextField jtfContactAddr = null;
	private JButton jbDelete = null;
	private JButton jbAudioCall = null;
	private JButton jbVideoCall = null;

	private JScrollPane jspContact = null;
	private JTree tree = null;
	private DefaultTreeModel model = null;
	private ArrayList<Contact> contacts = null;
	private ArrayList<DefaultMutableTreeNode> cnodes = null;
	private ArrayList<History> histories = null;
	private ArrayList<DefaultMutableTreeNode> hnodes = null;
	private DefaultMutableTreeNode contact = null;
	private DefaultMutableTreeNode history = null;

	private JPanel jpDialPanel = null;
	private JButton[] dialBtns = null;

	/**
	 * GUI variables.
	 */
	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JButton addContactButton;
	private javax.swing.JMenuBar fileMenuBar1;
	private javax.swing.JLabel imageLabel;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JMenu jMenu5;
	private javax.swing.JMenuItem jMenuItemConfiguration;
	private javax.swing.JMenuItem jMenuItemRegister;
	private javax.swing.JMenuItem jMenuItemUnregister;
	private javax.swing.JMenuItem jMenuItemExit;
	private javax.swing.JMenu jMenuStatus;
	private javax.swing.JPanel mainPanel;
	private javax.swing.JButton removeContactButton;
	// End of variables declaration//GEN-END:variables
	private javax.swing.JList jList1;
	private DefaultListModel listModel;
	private JRadioButtonMenuItem onlineJRadioButtonMenuItem;
	private JRadioButtonMenuItem awayJRadioButtonMenuItem;
	private JRadioButtonMenuItem offlineJRadioButtonMenuItem;
	private JRadioButtonMenuItem busyJRadioButtonMenuItem;
	ButtonGroup statusGroup;
	private javax.swing.JButton showConnectionButton;
	private ConnectionFrame connectionFrame;

	public MessengerManager getSipMeetingManager() {
		return sipMeetingManager;
	}

	public MessengerController getControllerMeeting() {
		return controllerMeeting;
	}

}
